package org.wmine.core;


import org.wmine.core.IProjectManager;
import org.wmine.core.IndexParserGenerator;
import org.wmine.algo.*;
import com.sun.corba.se.impl.orbutil.graph.Node;
//import com.sun.java.util.jar.pack.Attribute.Layout.Element;

import java.io.*;
import java.util.zip.*;
import java.util.*;

import javax.swing.text.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Element;
import org.w3c.dom.Text;


public class ProjectManager implements IProjectManager {
	FileOutputStream dest=null;
	FileInputStream src=null;
	ZipOutputStream out=null;
	ZipInputStream in=null;
	ZipEntry entry;
	public String currentProject=null;
	private static IProjectManager unicInstance=null;
	//to deal with index file
	static IndexParserGenerator ip;
	
	ArrayList<ProjectListener> projectListenerList;
	
	private ProjectManager() {
		projectListenerList = new ArrayList<ProjectListener>();
	}
	
	
	
	public static IProjectManager getUniqueInstance(){	
		if(unicInstance==null){	
			unicInstance=new ProjectManager();
			ip=new IndexParserGenerator();
		}
		return unicInstance;
	}
	public String getCurrentProject(){
		return currentProject;
	}
	public boolean createProject(String projectName,String parentDirectory){
		File f=new File(parentDirectory+"\\"+projectName+".zip");
		//System.out.println("Created project"+f.exists());
		if(!f.exists()){
			try{
				String basic=new String();
				dest = new FileOutputStream(parentDirectory+"\\"+projectName+".zip",true);
				out = new ZipOutputStream(new BufferedOutputStream(dest));
				out.putNextEntry(new ZipEntry("Index.xml"));
				BasAlgoWriter baw=new BasAlgoWriter("Index.xml","Project");
				baw.addElement("Name",projectName);
				basic=baw.getXMLString();
				out.write(basic.getBytes());
				out.close();
				dest.close();
			
				for(int i = 0;i < projectListenerList.size();i++) {
					projectListenerList.get(i).onProjectEvent(PROJECT_OPEN_EVENT);
				}
 				
				//File f=new File(parentDirectory+"\\"+projectName+".zip");
				//System.out.println("Created project"+f.exists());
				return true;
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		return false;
	}
	
	
	
	public void openProject(String projectName) throws InvalidProjectFileException {
		if(new File(projectName).exists()){
			try{
				currentProject=new String(projectName);
			//	System.out.println("Open Project");
				for(int i = 0;i < projectListenerList.size();i++) {
					projectListenerList.get(i).onProjectEvent(PROJECT_OPEN_EVENT);
				}
		
			}catch(Exception e){e.printStackTrace();}
		}
		//else
		//throw new InvalidProjectFileException("Project does not exist, try and create a new one...");
	}
	public void closeProject(){
		currentProject = null;
		for (int i = 0; i < projectListenerList.size(); i++) {
			projectListenerList.get(i).onProjectEvent(PROJECT_CLOSE_EVENT);
		}
	}
	public boolean fileExists(String fileName){
		/*try {	
		 src=new FileInputStream(currentProject);
		 in = new ZipInputStream(new BufferedInputStream(src));
		 //	System.out.println(in.);
		  while((entry=in.getNextEntry())!=null){
		  
		  if(fileName.equals(entry.getName())){
		  in.close();
		  src.close();
		  return true;
		  }
		  entry=null;
		  }
		  
		  
		  }	catch(Exception io){
		  io.printStackTrace();
		  }	
		  */
		String list_entries[]=list();
		for(int i=0;i<list_entries.length;i++)
			if(list_entries[i].equals(fileName))
				return true;
		
		return false;	
	}
	
	public String readFile(String fileName){
		byte read_data[] = null;
		try{
			
			if(currentProject!=null)
			{src=new FileInputStream(currentProject);
			in = new ZipInputStream(new BufferedInputStream(src));
			ZipFile zipfile = new ZipFile(currentProject);
			BufferedInputStream is=null;
			byte data[]=new byte[2];
			//int count,j=0;
			String[] file_list = null;
			Enumeration e=zipfile.entries();
			
			int count=0,j=0,i=0;
			for(;e.hasMoreElements() && e!=null;count++){
				e.nextElement();
			}
			file_list=new String[count];
			e=zipfile.entries();
			while(e.hasMoreElements())
				file_list[i++]=(e.nextElement()).toString();
			
			for( i=0;i<file_list.length;i++){
				if(file_list[i].equals(fileName)){
					is = new BufferedInputStream(zipfile.getInputStream(new ZipEntry(file_list[i])));
					read_data = new byte[is.available()];
					while (( count = is.read(data,0,1)) != -1){
						read_data[j]=data[0];
						j++;
					}	
					String string = new String(read_data);
					//	System.out.println(string);
					in.close();
					src.close();
					zipfile.close();
					return (string); 
				}
			}	
			/*ZipEntry entry=null ;	  
			 while((entry=in.getNextEntry())!=null)
			 {	
			 System.out.println(entry.getName());
			 if(fileName.equals(entry.getName()))
			 {	System.out.println("inside if");
			 is = new BufferedInputStream(zipfile.getInputStream(entry));
			 read_data = new byte[is.available()];
			 while (( count = is.read(data,0,1)) != -1)	{
			 read_data[i]=data[0];
			 i++;
			 
			 }
			 String string = new String(read_data);
			 System.out.println(string);
			 
			 return (string); 
			 
			 }
			 entry=null;
			 
			 
			 }*/
			}
			return null;
		}catch(IOException ioe){
			ioe.printStackTrace();
		}
		return null;
	}
	
	@SuppressWarnings("deprecation")
	public boolean writeFile(String fileName,String fileContent,String type,String subtype ,String description ){
		try{ 
			
			dest = new FileOutputStream(currentProject,true);
			out = new ZipOutputStream(new BufferedOutputStream(dest));
			String []fileNames=null;
			int i=0;
			ZipEntry entry1,entry2;
			fileNames=list();
			/*if(list() == null)
			 {	fileNames=new String[1];
			 fileNames[0]="Index.xml";
			 }
			 else
			 {	fileNames=list();
			 fileNames[fileNames.length-1]="Index.xml";
			 }*/
			
			//System.out.println(fileNames.length);
			
			for(i = 0 ;i < fileNames.length ;i++ ) {
				if(fileNames[i]!=null){
					//System.out.println("filename"+fileNames[i]);
					entry1 = new ZipEntry(fileNames[i]);
					
					String fileC=readFile(fileNames[i]);
					//System.out.println("File Contents : "+fileC);
					byte to_write[]=new byte[fileC.length()]; 
					out.putNextEntry(entry1);
					fileC.getBytes(0,fileC.length(),to_write,0);
					out.write(to_write, 0,(int)fileC.length());
					entry1=null;
				}
			}
			
			
			entry2 = new ZipEntry(fileName);
			
			byte to_write[]=new byte[fileContent.length()]; 
			out.putNextEntry(entry2);
			fileContent.getBytes(0,fileContent.length(),to_write,0);
			out.write(to_write, 0,(int)fileContent.length());
			out.closeEntry();
			out.close();
			dest.close();
			
			//add to index file
			
			
			
			String values[]=new String[4];
			
			values[0]=fileName;
			
			values[1]=type;
			
			values[2]=subtype;
			values[3]=description;
			ip.addFile(values);
			
		}catch(Exception e){e.printStackTrace();}
		return true;
	}
	
	@SuppressWarnings("deprecation")
	public boolean writeFile(String fileName,String fileContent){
		try{ 
			
			dest = new FileOutputStream(currentProject,true);
			out = new ZipOutputStream(new BufferedOutputStream(dest));
			String fileNames[]=null;
			int i=0;
			ZipEntry entry1,entry2;
			fileNames=list();
			/*if(list() == null)
			 {	fileNames=new String[1];
			 fileNames[0]="Index.xml";
			 }
			 else
			 {	fileNames=list();
			 fileNames[fileNames.length-1]="Index.xml";
			 }*/
			//System.out.println(fileNames.length);
			
			for(i = 0 ;i < fileNames.length ;i++ ) {
				//System.out.println(fileNames[i]);
				if(!fileNames[i].equals("Index.xml")){
					if(fileNames[i]!=null){
						entry1 = new ZipEntry(fileNames[i]);
						
						String fileC=readFile(fileNames[i]);
						//	System.out.println("File Contents : "+fileC);
						byte to_write[]=new byte[fileC.length()]; 
						out.putNextEntry(entry1);
						fileC.getBytes(0,fileC.length(),to_write,0);
						out.write(to_write, 0,(int)fileC.length());
						entry1=null;
					}
				}
			}
			
			
			entry2 = new ZipEntry(fileName);
			
			byte to_write[]=new byte[fileContent.length()]; 
			out.putNextEntry(entry2);
			fileContent.getBytes(0,fileContent.length(),to_write,0);
			out.write(to_write, 0,(int)fileContent.length());
			out.closeEntry();
			out.close();
			dest.close();
		}catch(Exception e){e.printStackTrace();}
		return true;
	}	
	
	
	private String[] list(){
		
		String[] file_list=null;
		
		ZipFile zipfile=null ;
		try {
			//System.out.println("CurrentProject>>"+currentProject);
			
			if(currentProject != null)
				zipfile = new ZipFile(currentProject);
			
			
			Enumeration e=zipfile.entries();
			int count=0,i=0;
			for(;e.hasMoreElements() && e!=null;count++){
				e.nextElement();
			}
			file_list=new String[count];
			e=zipfile.entries();
			while(e.hasMoreElements() && e!=null)
				file_list[i++]=(e.nextElement()).toString();
			
			zipfile.close();
		}
		catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace(); 
		}
		
		return file_list;
	}
	
	public String[] getSubtypesNamesArray(String type){
		return ip.getIndexSubtypes(type);
	}

	public static void main(String args[]){
		IProjectManager pg=ProjectManager.getUniqueInstance();
		try {
			pg.createProject("sh1","e:\\");
			pg.openProject("e:\\sh1.zip");
			//pg.openProject("e:\\test");
			
			//String list[]=pg.getFileNamesArray();
			//System.out.println(list.length);
			//for(int i = 0;i < list.length ; i++)
			//	System.out.println(list[i]);
			System.out.println(pg.isProjectOpened());
			//System.out.println(pg.readFile("Index.xml"));
			System.out.println(pg.writeFile("shree","Some more data,again","algo","classification","nice one"));
			
			//System.out.println(pg.readFile("shree"));
			//System.out.println(pg.readFile("Index.xml"));
			System.out.println(pg.writeFile("abc","Some more data,again new in abc","preprocess","classification","nice one"));
			System.out.println("the contents of abc are>>"+pg.readFile("abc"));
			System.out.println(pg.readFile("Index.xml"));
			String x[]=pg.getFileNamesArray("algo");
			for(int i=0;i<x.length;i++)
				System.out.println(x[i]);
			String y[]=pg.getFileNamesArray("preprocess");
			for(int i=0;i<y.length;i++)
				System.out.println(y[i]);
			String z[]=pg.getFileNamesArray(null);
			for(int i=0;i<z.length;i++)
				System.out.println(z[i]);
			System.out.println(pg.writeFile("pqr","Some more data,again new in pqr","preprocess","classification","nice one"));
			pg.writeFile("Preprocessed.xml","<dataset><table><tablename>Sales</tablename><attributes><size>5</size><attribute><name>User ID</name><type>Integer</type></attribute><attribute><name>Name</name><type>String</type></attribute><attribute><name>Age</name><type>Integer</type></attribute><attribute><name>experience</name><type>Integer</type></attribute><attribute><name>salary (1000s)</name><type>Integer</type></attribute></attributes><tuples><size>20</size><tuple>1,A1,25,3,30</tuple><tuple>2,A2,30,8,57</tuple><tuple>3,A3,45,9,64</tuple></tuples></table></dataset>","preprocess","clean","none");
			 y=pg.getFileNamesArray("preprocess");
			for(int i=0;i<y.length;i++)
				System.out.println(y[i]);
			z=pg.getFileNamesArray(null);
			for(int i=0;i<z.length;i++)
				System.out.println(z[i]);
			System.out.println(pg.readFile("Index.xml"));
			//System.out.println(pg.getFileNamesArray("preprocess"));
			//System.out.println(pg.writeFile("sh","Some more data,again,but new file"));
			//String list1[]=pg.getFileNamesArray();
			//System.out.println(list1.length);
			//for(int i = 0;i < list1.length ; i++)
			//	System.out.println(list1[i]);
			
			
			//			System.out.println("Zip contains "+list.length);
			
			//	System.out.println("shree"+pg.fileExists("shree"));
			//	System.out.println("sh"+pg.fileExists("sh"));
			//	System.out.println("sh1"+pg.fileExists("sh1"));
			//		System.out.println(pg.isOpen());
			//			System.out.println(pg.fileExists("shree"));
			//			pg.writeFile("shree","this has to work!!!!!");
			
			//pg.writeFile("harsha","this has a Harsha File!!!!");*/
			//	 System.out.println(pg.readFile("stat-result.xml"));
			//	 System.out.println(pg.readFile("Freq-Dist.xml"));
			
			
			/*
			 pg.writeFile("harsha","hope this works fine!!!!!");
			 System.out.println(pg.fileExists("harsha"));
			 
			 String list1[]=pg.list();
			 i=0;
			 while(list[i]!=null)
			 System.out.println("list"+list[i++]);
			 System.out.println(pg.readFile("harsha"));
			 System.out.println(pg.readFile("shree"));*/
		}catch(Exception e) {
			System.out.println(e);
			
		}
	}
	
	
	public boolean isProjectOpened() {
		if(currentProject!=null) 
			return true;
		return false;
	}
	
	
	
	public String[] getFileNamesArray(String type) {
		return ip.getIndexFiles(type);
	}
	public void addProjectListener(ProjectListener projectListener) {
		projectListenerList.add(projectListener);
	}



	public void removeProjectListener(ProjectListener projectListener) {
		projectListenerList.remove(projectListener);		
	}
}